import inspect
import time
from datetime import datetime
import os
from colorama import Fore
from main import DIR
import functools
timeout = 10

def case(text):
    """用于输出case相关信息，如用例名称，用例描述等"""
    formatted_time = datetime.now().strftime('%H:%M:%S:%f')[:-3]
    stack = inspect.stack() # 获取当前调用栈的信息
    # 获取待用case 函数的文件名以及代码行号
    code_path = f'{os.path.basename(stack[1].filename)}:{stack[1].lineno}'
    content = f'[Case]{formatted_time}-{code_path}>>{text}'
    print(Fore.LIGHTCYAN_EX + content)
    str_time = datetime.now().strftime("%Y%m%d")
    log_file = os.path.join(DIR, 'logs', f'{str_time}_info.log')
    with open(file=log_file, mode='a', encoding='utf-8') as f:
        f.write(content + '\n')


def info(text):
    """用于输出用例执行时的数据，如：用例步骤描述，请求数据，返回数据等"""
    formatted_time = datetime.now().strftime('%H:%M:%S:%f')[:-3]
    stack = inspect.stack()
    code_path = f'{os.path.basename(stack[1].filename)}:{stack[1].lineno}'
    content = f'[Info]{formatted_time}-{code_path}>>{text}'
    print(Fore.LIGHTGREEN_EX + content)
    str_time = datetime.now().strftime("%Y%m%d")
    log_file = os.path.join(DIR, 'logs', f'{str_time}_info.log')
    with open(file=log_file, mode='a', encoding='utf-8') as f:
        f.write(content + '\n')

def error(text):
    """用于输出用例执行时的数据，如：用例步骤描述，请求数据，返回数据等"""
    formatted_time = datetime.now().strftime('%H:%M:%S:%f')[:-3]
    stack = inspect.stack()
    code_path = f'{os.path.basename(stack[1].filename)}:{stack[1].lineno}'
    content = f'[error]{formatted_time}-{code_path}>>{text}'
    print(Fore.LIGHTCYAN_EX + content)
    str_time = datetime.now().strftime("%Y%m%d")
    # 将error log 写入 info.log文件，确保log的完整性
    log_file = os.path.join(DIR, 'logs', f'{str_time}_info.log')
    with open(file=log_file, mode='a', encoding='utf-8') as f:
        f.write(content + '\n')
    # 将 error 单独写入 error log，便于查看error 信息
    log_file = os.path.join(DIR, 'logs', f'{str_time}_error.log')
    with open(file=log_file, mode='a', encoding='utf-8') as f:
        f.write(content + '\n')

def case_decoration(func):
    """装饰器函数：可以自动的为每个测试用例输出case级别的log信息，
    并且为测试用例添加 执行统计时间和超时检测"""
    @functools.wraps(func) # 解决参数冲突问题
    def case_improve(*args, **kwargs):
        start = time.perf_counter() # 获取当前时间戳，记录测试用例执行的开始时间
        class_name = args[0].__class__.__name__ # 获取类名
        method_name = func.__name__ #获取方法的名称
        docstring = inspect.getdoc(func) # 获取方法注释
        case('-----------------------------------------------')
        case(f'Method Name:{method_name}, Class Name:{class_name}')
        case(f'Test Description:{docstring} ')
        func(*args, **kwargs)  # 执行测试用例
        end = time.perf_counter()
        handle_time = end - start
        case('Case run time: %.2fs' % handle_time)
        if handle_time > timeout:
            error('case run timeout!')

    return case_improve

def class_case_decoration(cls):
    """用例的日志类级别装饰器，用于自动为类中以 testCase 开头的方法应用 case_decoration 装饰器"""
    # 获取类中所有的成员方法
    for name, method in inspect.getmembers(cls, inspect.isfunction):
        if name.startswith('testCase'):
            # 只对以 testCase 开头 的方法进行装饰
            setattr(cls, name, case_decoration(method))
    return cls



